/*
 * Log.java	2008/07/28
 *
 * Copyright 2008 Web & Zen Multimedia, All rights reserved.
 * Use is subject to license terms.
 */
package it.wzm.lightweightlog;

import java.io.Serializable;
import java.util.Properties;


/**
 * 
 * @author Leonardo Celati
 * @version 1.0
 */
public class Log implements Constant,Serializable {

	/**
	 * As required by serialization
	 */
	private static final long serialVersionUID = 595978219476446888L;
	/**
     * Service log
     */
    private static boolean serviceLogEnabled;
    
    /**
     * Status
     */
    public enum Status {
    	INIT,
    	RUNNING,
    	FAILURE,
    	SHUTDOWN,
    	DEFAULT,
    }
    /**
     * Set the name for this log...
     */
    private String name;
    /**
     * Last used time
     */
    private long lastUsed;
    /**
     * Current status of log
     */
    private Status status;
	/**
	 * Properties holder
	 */
    private Properties p;
    
    /**
     * Build a default log
     */
    public Log() {
    	// building a default set of properties...
    	//p = new Properties();    	
    	// init log...
    	//this.setStatus(Status.DEFAULT);
    	//this.init(p);
    }
       
    /**
     * Set the last used time
	 * @param lastUsed the lastUsed to set
	 */
	void setLastUsed(long lastUsed) {
		this.lastUsed = lastUsed;
	}

	/**
	 * @return the lastUsed
	 */
	public long getLastUsed() {
		return lastUsed;
	}

	/**
     * Return the name of this logger
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * Set name for this logger
	 * @param name the name to set
	 */
	void setName(String name) {
		this.name = name;
	}
	
	/**
	 * Set properties
	 * @param valid set of properties
	 */
	void setProperties(Properties p) {
		this.p=p;
	}

	/**
     * Setter for status
     * @param status status for Log
     */
    private void setStatus(Status status) {
		this.status = status;
	}

    /**
     * Getter for status
     * @return Status for logger
     */
	public Status getStatus() {
		return status;
	}

	/**
     * Is service log enabled ?
     * @return true or false
     */
    public static boolean isServiceLogEnabled() {
		return serviceLogEnabled;
	}

    /**
     * 
     */
    public void init() {    	
    }
    
    
    /**
     * Private method for init our Log
     */
    protected void init(Properties p) {

    	// basic assert...
    	assert(p != null && !p.isEmpty()): "Property null or empty";

    	// acquire our set of properties
    	this.p=p;
    }
    

    
    /**
     * Get all debug level
     * @param tolog The object to be logged
     */
    public final void debug(Object o) {
        this.add(o, Severity.DEBUG);
    }

    /**
     * Get all info level
     * @param tolog The object to be logged
     */
    public final void info(Object o) {
        this.add(o, Severity.INFO);
    }

    /**
     * Get all warn level
     * @param tolog The object to be logged
     */
    public final void warn(Object o) {
        this.add(o, Severity.WARN);
    }

    /**
     * Get all error level
     * @param tolog The object to be logged
     */
    public final void error(Object o) {
        this.add(o, Severity.ERROR);
    }

    /**
     * Get all fatal level
     * @param tolog The object to be logged
     */
    public final void fatal(Object o) {
        this.add(o, Severity.FATAL);
    }
    
    /**
     * Build an Entry from the passed Object and Store it in Queue
     * @param o Object to log
     * @param severity The level of Severity
     * @param t A throwable for getting the caller of this error
     */
    protected void add(Object o, Severity severity) {
    	
        // log holder
        Entry e = null;
        // decide if we want to log a string or an exception
        if (o != null && o instanceof Exception) {
            e = new Entry(getName(),new Exception((Exception) o), severity, System.currentTimeMillis());
        } else {
            //e = new Entry(getName(),tolog, severity, t.getStackTrace()[t.getStackTrace().length - 1].getClassName(), System.currentTimeMillis());
        	e = new Entry(getName(),o, severity, this.getName(), System.currentTimeMillis());
        }
        // in service log...
        //serviceLog(e.getLine());
        try {
        LogFactory.getQueue().push(e);
        } catch (QueueException qe) {
        	System.out.println(e);
        	System.out.println(qe);
        }
        
        // store in queue        
    }
    


    /**
     * Facility for logging everything passed, which will be written to System.err. Useful for debugging.
     * @param o The object to write to log
     */
    public void serviceLog(Object o) {
    	
        // basic check...
        if (!serviceLogEnabled) {
            return;
        }
        // building our entry
        Entry e;
        // check if we want to log instance of Exception or not...
        if (o != null && o instanceof Exception) {
            e = new Entry(getName(),new Exception((Exception) o), Severity.SERVICE, System.currentTimeMillis());
        } else {
            Throwable t = new Throwable();
            e = new Entry(getName(),o, Severity.SERVICE, t.getStackTrace()[t.getStackTrace().length - 1].getClassName(), System.currentTimeMillis());
        }
        // finally logging
        System.err.print(e.getLine());
    }

    /**
     * Facility for logging a passed  Entry which will be written to System.err. Useful for debugging.
     * @param o The object to write to log
     */
    public static <E extends Entry> void serviceLog(E e) {
        System.err.print(e.getLine());
    }
    
    /**
     * Dump E to service log
     * @param <E> 
     * @param e Anything extending Entry
     */
	protected  <E extends Entry> void add(E e) {
        // finally add to queue...
    	// we will try to store entry in Queue...
    	// if we fail we try to recover the Queue.
        try {
			LogFactory.getQueue().push(e);
		} catch (QueueException ex) {
			// let's behave differently with the Queue status	
						
		} catch (NullPointerException ex) {
			// if we get here getQueue returned null
			// we are in trouble deep...the Queue has probably crashed
			// let's ask the Log to init again...
			
		}
    }
	
    /**
     * Overwriting the inherited method from Object
     * @return Valid string
     */
    @Override
    public String toString() {
        
        StringBuffer sb = new StringBuffer();
        
        for (Object key: p.keySet()) {
            if (((String)key).indexOf(Constant.PROP_ROOT + "log." ) > -1) {
                sb.append( "," +  ((String)key).replaceAll(Constant.PROP_ROOT + "queue.", "") + "=" +  p.get(key) );
            }
        }
        //  returning...
        return super.toString() + " {hc=" + this.hashCode() + ", name=" + this.getName() + ", last used=" + this.getLastUsed() + sb + "}" ;
    }    
    
    
    /**
     * Extending class can implements their own cleanup stuff here
     */
    public void shutdown() {    	
    }
    
 
}